package com.ruoyi.app.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.app.service.LoginService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.domain.JkFllowup;
import com.ruoyi.domain.JkUser;
import com.ruoyi.framework.security.wechat.WeChatAuthenticationToken;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.service.IJkFllowupService;
import com.ruoyi.service.IJkUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class LoginServiceImpl implements LoginService {

    private static final Logger log = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IJkUserService jkUserService;

    @Autowired
    private IJkFllowupService fllowupService;

    @Value("${wechat.appId}")
    private String appId;

    @Value("${wechat.appSecret}")
    private String appSecret;

    @Override
    public AjaxResult getSessionKey(String code) {
        log.info("code--->："+code);
        //拼接url
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret="
                + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        String result = HttpUtils.sendGet(url);
        log.info("result为："+result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        //获取微信用户的openid和session_key
        String openid = jsonObject.getString("openid");
        String session_key = jsonObject.getString("session_key");
        String unionid = jsonObject.getString("unionid");
        if(StringUtils.isEmpty(openid)){
            return AjaxResult.error("获取用户openid失败！");
        }
        if(StringUtils.isEmpty(session_key)){
            return AjaxResult.error("获取session_key失败！");
        }
        if(StringUtils.isEmpty(unionid)){
            return AjaxResult.error("获取unionid失败！");
        }
        return AjaxResult.success().put("open_id",openid).put("session_key",session_key).put("union_id",unionid);
    }

    @Override
    public AjaxResult getPhone(String code, String userId) {
        log.info("手机号获取凭证: {}", code);
        try {
            //通过appid和secret来获取token
            String tokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
            String tokenResult = HttpUtils.sendGet(tokenUrl);
            JSONObject tokenObj = JSONObject.parseObject(tokenResult);
            String accessToken = tokenObj.getString("access_token");
            if(StringUtils.isEmpty(accessToken)){
                return AjaxResult.error("access_token获取失败");
            }
            //通过token和code来获取用户手机号
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
            //封装请求体
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("code", code);

            //封装请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(paramMap,headers);
            //通过RestTemplate发送请求，获取到用户手机号码
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
            String errmsg = response.getBody().getString("errmsg");
            if (errmsg.equals("ok")) {
                JSONObject phoneInfoJson = response.getBody().getJSONObject("phone_info");
                log.info("获取手机号信息成功："+phoneInfoJson);
                String phoneNumber = phoneInfoJson.getString("phoneNumber");
                JkUser jkUser = new JkUser();
                jkUser.setId(Long.valueOf(userId));
                jkUser.setUserPhone(phoneNumber);
                jkUserService.updateJkUser(jkUser);
                return AjaxResult.success(phoneNumber);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error("手机号获取失败");
    }

    @Override
    public AjaxResult loginByWechat(String encryptedData, String sessionKey, String iv, String openId, String unionId) throws Exception {
        String decryptStr = decrypt(encryptedData, sessionKey, iv);
        log.info("解密信息为："+decryptStr);
        JSONObject userInfo = JSONObject.parseObject(decryptStr);
        if (ObjectUtils.isEmpty(userInfo)) {
            return AjaxResult.error("信息解密失败,请重新登录");
        }
        // 用户验证
        Authentication authentication = null;

        JkUser jkUser = new JkUser();
        jkUser.setOpenId(openId);
//        jkUser.setUnionId(unionId);
        JkUser user = jkUserService.selectJkUserByCondition(jkUser);
        if(user==null){
            JkUser new_user = new JkUser();
            String nickname = userInfo.getString("nickName");
            String headimgurl = userInfo.getString("avatarUrl");
            String sex = userInfo.getString("gender");
            new_user.setOpenId(openId);
            new_user.setUnionId(unionId);
            new_user.setUserName(nickname);
            new_user.setUserNick(nickname);
            new_user.setUserPhoto(headimgurl);
            new_user.setUserSex(Integer.valueOf(sex));
            new_user.setStatus(1);
            jkUserService.insertJkUser(new_user);
            user = new_user;
        }
        JkFllowup jkFllowup = new JkFllowup();
        jkFllowup.setUserId(user.getId());
        List<JkFllowup> jkFllowups = fllowupService.selectJkFllowupList(jkFllowup);
        try {
            authentication = authenticationManager.authenticate(new WeChatAuthenticationToken(openId));
        }catch (Exception e){
            throw e;
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        SysUser sysUser = new SysUser();
        sysUser.setUserName(user.getUserName());
        sysUser.setPassword("123456");
        loginUser.setUser(sysUser);
        // 生成token
        String token = tokenService.createToken(loginUser);
        return AjaxResult.success().put("token",token).put("user",user).put("sfCount",jkFllowups.size());
    }
    private String decrypt(String encryptedData, String sessionKey, String encryptedIv) throws Exception {
        // 转化为字节数组
        byte[] key = Base64.decode(sessionKey);
        byte[] iv = Base64.decode(encryptedIv);
        byte[] encData = Base64.decode(encryptedData);
        // 假如密钥缺乏16位，那么就补足
        int base =16;
        if (key.length % base !=0) {
            int groups = key.length / base +(key.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp,(byte) 0);
            System.arraycopy(key,0,temp,0,key.length);
            key = temp;
        }
        // 假如初始向量缺乏16位，也补足
        if (iv.length % base !=0) {
            int groups = iv.length / base +(iv.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp,(byte) 0);
            System.arraycopy(iv,0,temp,0,iv.length);
            iv = temp;
        }
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        String resultStr = null;
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
            cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
            resultStr = new String(cipher.doFinal(encData),"UTF-8");
        } catch (Exception e){
            log.info("解析错误");
            e.printStackTrace();
        }
        // 解析加密后的字符串
        return resultStr;
    }

}
